package coderead.agent;


import coderead.agent.jvmtool.Jad;
import javassist.*;

import java.io.IOException;
import java.lang.instrument.*;
import java.security.ProtectionDomain;

/*
* test
* */
public class MyAgent {
    // 加载时启动
    public static void premain(String args,
                               Instrumentation instrumentation) {}
//        System.out.println("premain");
//        HelloWorld helloWorld = new HelloWorld();
//        // 添加类加载过滤器
//        instrumentation.addTransformer(new ClassFileTransformer() {
//            @Override
//            public byte[] transform(ClassLoader loader, String className,
//                                    Class<?> classBeingRedefined,
//                                    ProtectionDomain protectionDomain,
//                                    byte[] classfileBuffer) throws IllegalClassFormatException {
//
//                if (!"coderead/agent/HelloWorld".equals(className)) {
//                    return null;
//                }
//
//                // javassist
//                try {
//                    ClassPool pool=new ClassPool();
//                    pool.appendClassPath(new ByteArrayClassPath("coderead.agent.HelloWorld",classfileBuffer));
//                    pool.appendSystemPath();
//                    CtClass ctClass = pool.get("coderead.agent.HelloWorld");
//                    CtMethod ctMethod = ctClass.getDeclaredMethod("hello");
//                    ctMethod.insertBefore("System.out.println(\"插入前置逻辑\");");
//                    return ctClass.toBytecode();
//                } catch (NotFoundException | CannotCompileException | IOException e) {
//                    e.printStackTrace();
//                }
//                return null;
//            }
//        },true);
//        // 重新走过滤器
//        try {
//            instrumentation.retransformClasses(HelloWorld.class);
//        } catch (UnmodifiableClassException e) {
//            e.printStackTrace();
//        }
//        // 重新定义
//        try {
//            ClassPool pool=new ClassPool();
//            pool.appendSystemPath();
//            CtClass ctClass = pool.get("coderead.agent.HelloWorld");
//            CtMethod ctMethod = ctClass.getDeclaredMethod("hello");
//            ctMethod.insertAfter("System.out.println(\"插入后置逻辑\");");
//            instrumentation.redefineClasses(new ClassDefinition(HelloWorld.class,ctClass.toBytecode()));
//        } catch (NotFoundException | CannotCompileException | IOException | UnmodifiableClassException | ClassNotFoundException e) {
//            e.printStackTrace();
//        }
//        // 练习，总结
////        helloWorld.hello();
//    }

    // 运行时启动
    public static void agentmain(String args,
                                 Instrumentation instrumentation) {
        System.out.println("agentmain");
        instrumentation.addTransformer(new ClassFileTransformer() {
            @Override
            public byte[] transform(ClassLoader loader, String className,
                                    Class<?> classBeingRedefined,
                                    ProtectionDomain protectionDomain,
                                    byte[] classfileBuffer) throws IllegalClassFormatException {
                // javassist
                if (!"coderead/agent/HelloWorld".equals(className)) {
                    return null;
                }
                try {
                    ClassPool pool=new ClassPool();
                    pool.appendSystemPath();
                    CtClass ctClass = pool.get("coderead.agent.HelloWorld");
                    CtMethod ctMethod = ctClass.getDeclaredMethod("hello");
                    ctMethod.insertBefore("System.out.println(\"插入前置逻辑\");");
                    return ctClass.toBytecode();
                } catch (NotFoundException | CannotCompileException | IOException e) {
                    e.printStackTrace();
                }
                return null;
            }
        },true);

        try {
            instrumentation.retransformClasses(HelloWorld.class);
        } catch (UnmodifiableClassException e) {
            e.printStackTrace();
        }
//        try {
//            System.out.println(Jad.decompiler("coderead.agent.HelloWorld"));
//            new HelloWorld().hello();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }
}
